package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.mapper.CartInfoMapper;
import com.atguigu.gmall.cart.service.CartInfoService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author: lx
 * @Time: 10:46
 * @Description:
 */
@Service
public class CartInfoServiceImpl implements CartInfoService {

    @Autowired
    private CartInfoMapper cartInfoMapper;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private RedisTemplate redisTemplate;

    //加入购物车
    //1:同款商品要求合并数量
    //2:不同款商品 作为新款追加
    @Override
    public void addToCart(Long skuId, Integer skuNum, String userId) {

        //1:查询购物车列表
              //优先前 使用DB  select * from cart_info where user_id = 3 and sku_id = 1
   /*     CartInfo cartInfo = cartInfoMapper.selectOne(new QueryWrapper<CartInfo>()
                .eq("user_id", userId).eq("sku_id", skuId));*/
              //优先后  使用Redis  实时跟MysqlDB之间同步
        CartInfo cartInfo = (CartInfo) redisTemplate.opsForHash().get(RedisConst.USER_KEY_PREFIX +
                userId + RedisConst.USER_CART_KEY_SUFFIX, skuId.toString());
        //2:判断是否为同款
        if(null != cartInfo){
            //同款 合并数量
            cartInfo.setSkuNum(cartInfo.getSkuNum() + skuNum);
            //选中状态
            cartInfo.setIsChecked(CartInfo.isCheckedOK);
            //更新
            cartInfoMapper.updateById(cartInfo);//Canal 同步的Redis缓存中
        }else{
            //追加新款
            cartInfo = new CartInfo();
            //用户ID
            cartInfo.setUserId(userId);
            //库存ID
            cartInfo.setSkuId(skuId);
            //设置数量
            cartInfo.setSkuNum(skuNum);
            //选中
            cartInfo.setIsChecked(CartInfo.isCheckedOK);

            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            //价格 购物车加入时的价格
            cartInfo.setCartPrice(skuInfo.getPrice());
            //  实时价格
            cartInfo.setSkuPrice(skuInfo.getPrice());
            //标题
            cartInfo.setSkuName(skuInfo.getSkuName());
            //图片
            cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
            //保存新款
            cartInfoMapper.insert(cartInfo);//同步Redis缓存
        }

    }
    //根据skuId查询一个购物车
    @Override
    public CartInfo findCartInfoBySkuId(Long skuId, String userId) {
        //TimeUnit.MILLISECONDS.sleep(3);//3ms
        CartInfo cartInfo = (CartInfo) redisTemplate.opsForHash().get(RedisConst.USER_KEY_PREFIX +
                userId + RedisConst.USER_CART_KEY_SUFFIX, skuId.toString());
        if(null == cartInfo){
            // 备用  平级处理
            //TimeUnit.MILLISECONDS.sleep(3);//3ms
            cartInfo = cartInfoMapper.selectOne(new QueryWrapper<CartInfo>()
                    .eq("user_id", userId).eq("sku_id", skuId));
        }
        return  cartInfo;
    }

    //去购物车结算
    @Override
    public List<CartInfo> cartList(String userId, String userTempId) {
        //1:用户是否登录了
        if(!StringUtils.isEmpty(userId)){
            //登录了 真实用户ID
            if(!StringUtils.isEmpty(userTempId)){
                //合并
                return mergeCartInfoList(userId,userTempId);
            }else{
                //无临时用户 直接返回真实用户的购物车集合 即可
                return getCartInfoList(userId);
            }
        }else{
            //未登录 临时用户ID 直接返回临时用户购物车集合 即可
            return getCartInfoList(userTempId);
        }
    }

    //选中或取消 购物车
    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = requestAttributes.getRequest();
        String userId = AuthContextHolder.getUserId(request);
        if(StringUtils.isEmpty(userId)){
            userId = AuthContextHolder.getUserTempId(request);
        }
        CartInfo cartInfo = new CartInfo();
        cartInfo.setIsChecked(isChecked);
        cartInfoMapper.update(cartInfo,new QueryWrapper<CartInfo>().
                eq("user_id",userId).eq("sku_id",skuId));
    }


    //用户选中要购买的商品清单
    @Override
    public List<CartInfo> findCartListByChecked(String userId) {
        List<CartInfo> cartInfoList = getCartInfoList(userId);
        return  cartInfoList.stream().filter(cartInfo -> {
            return cartInfo.getIsChecked().equals(CartInfo.isCheckedOK);
        }).collect(Collectors.toList());
    }

    //合并
    private List<CartInfo> mergeCartInfoList(String userId, String userTempId) {
        //获取购物车
        List<CartInfo> userIdCartInfoList = getCartInfoList(userId);
        List<CartInfo> userTempIdCartInfoList = getCartInfoList(userTempId);
        //1：判断真实用户是否有购物车
        if(!CollectionUtils.isEmpty(userIdCartInfoList)){
            //有真实购物车
            //2:判断临时用户的购物车是否存在
            if(!CollectionUtils.isEmpty(userTempIdCartInfoList)){

                Map<Long, CartInfo> userIdCartInfoMap = userIdCartInfoList.stream()
                        .collect(Collectors.toMap(CartInfo::getSkuId, cartInfo -> cartInfo));
                //Map K:skuId V:CartInfo
                //Map K:skuId V:CartInfo
                //真实有 临时还有 合并
                userTempIdCartInfoList.forEach(userTempIdCartInfo -> {
                    //--是否在真实购物车集合已经存在了
                    CartInfo userIdCartInfo = userIdCartInfoMap.
                            get(userTempIdCartInfo.getSkuId());
                    if(null != userIdCartInfo){
                        //--存在了就追加数量
                        userIdCartInfo.setSkuNum(userTempIdCartInfo.getSkuNum() +
                                userIdCartInfo.getSkuNum());
                        //更新真实用户对应的购物车数量
                        cartInfoMapper.updateById(userIdCartInfo);
                        //删除临时用户的（相同款）
                        cartInfoMapper.deleteById(userTempIdCartInfo.getId());

                    }else{
                        //--不存在添加新款
                        userIdCartInfoMap.put(userTempIdCartInfo.getSkuId(),userTempIdCartInfo);
                        //更新购物车的user_id 为真实ID
                        userTempIdCartInfo.setUserId(userId);
                        cartInfoMapper.updateById(userTempIdCartInfo);
                    }
                });
                //清理临时用户的缓存
                redisTemplate.delete(RedisConst.USER_KEY_PREFIX +
                        userTempId + RedisConst.USER_CART_KEY_SUFFIX);
                //返回合并后购物车集合
                return new ArrayList<>(userIdCartInfoMap.values());
            }else{
                //无临时用户的购物车
                return userIdCartInfoList;
            }
        }else{
            //无真实购物车
            //更新cart_info  user_id  改成真实用户的
            CartInfo cartInfo = new CartInfo();
            cartInfo.setUserId(userId);
            cartInfoMapper.update(cartInfo,new QueryWrapper<CartInfo>()
              .eq("user_id",userTempId));
            //清理临时用户的缓存
            redisTemplate.delete(RedisConst.USER_KEY_PREFIX +
                    userTempId + RedisConst.USER_CART_KEY_SUFFIX );
            return userTempIdCartInfoList;//显示页面购物车集合使用的
        }



    }

    //查询当前用户购物车集合
    public List<CartInfo> getCartInfoList(String userId){
        //1:缓存中查询
        List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(RedisConst.USER_KEY_PREFIX
        + userId + RedisConst.USER_CART_KEY_SUFFIX);
        //2:兜底 一般是使用不到的
        if(CollectionUtils.isEmpty(cartInfoList)){
            cartInfoList = cartInfoMapper.
                    selectList(new QueryWrapper<CartInfo>().eq("user_id",userId));
        }
        //实时价格
        cartInfoList.forEach(cartInfo -> {
            cartInfo.setSkuPrice(productFeignClient.getPrice(cartInfo.getSkuId()));
        });
        //排序  List<CartInfo>  cartInfo.get(0) cartInfo.get(1) cartInfo.get(2)
        cartInfoList = cartInfoList.stream().sorted((CartInfo o1,CartInfo o2) -> {
            return  o2.getId().intValue() - o1.getId().intValue();
        }).collect(Collectors.toList());
       return cartInfoList;
    }
}
